
// INCLUDES ********************************************************************

#include "Scene.h"

#include "Vector2D.h"

#include "Timer.h"

#include "GameController.h"

#include "Configuration.h"

#include "FileUtils.h"

#include "TextureCache.h"

#include "Function.h"

#include <sstream>


// NAMESPACES ******************************************************************

using namespace Meteor;

namespace 
{
    const int gLabelFontSize = 16;
    
    const Vector2D gLabelPosition( 10, 10);
}

// *****************************************************************************

#pragma mark -
#pragma mark Constructor
// -----------------------------------------------------------------------------

GameController::GameController()

: mCurrentScene( nullptr), mFPSLabel( "Verdana.ttf")
{
    mFPSLabel.SetFontSize( gLabelFontSize);
    
    mFPSLabel.SetPosition( gLabelPosition.X(), gLabelPosition.Y());

    mViewController = [[EAGLViewController alloc] init];
}

// -----------------------------------------------------------------------------

GameController::~GameController()
{
    [mViewController release];
}

// -----------------------------------------------------------------------------

EAGLViewController* GameController::ViewController()
{
    return mViewController;
}


#pragma mark -
#pragma mark Scene handling
// -----------------------------------------------------------------------------

void GameController::RunScene( Scene* scene)
{
    if ( mCurrentScene)
    {
        Function* transitionFunction = new MemberFunction<GameController, Scene*>( this, &GameController::FadeSceneIn, scene);
        
        mCurrentScene->ApplyTween( mCurrentScene->TransitionTween( 1.0f, 0.0f, 1.0f), transitionFunction);
    }
    else
    {
        mCurrentScene = scene;
    }
}

// -----------------------------------------------------------------------------

void GameController::FadeSceneIn( Scene* scene)
{
    Logger::DebugLog( "scene faded out and called back, new scene inserted now");
    
    delete mCurrentScene;
    
    mCurrentScene = scene;
    
    mCurrentScene->ApplyTween( scene->TransitionTween( 0.0f, 1.0f, 1.0f));
}


#pragma mark -
#pragma mark FPS label
// -----------------------------------------------------------------------------

void GameController::DisplayFPS( const bool displayFPS)
{
    mFPSLabel.SetVisible( displayFPS);
}

#pragma mark -
#pragma mark Periodic updates
// -----------------------------------------------------------------------------

void GameController::Pause()
{
    mPaused = true;
}

// -----------------------------------------------------------------------------

void GameController::Resume()
{
    mPaused = false;
}

#pragma mark -
#pragma mark Periodic updates
// -----------------------------------------------------------------------------

void GameController::Update()
{
    static uint64_t lastTime = 0;
    
    const uint64_t thisTime = Timer::GetCurrentTime();

    const double deltaTime = ( thisTime - lastTime) / Timer::ConversionFactor;

    lastTime = thisTime;
        
    std::ostringstream fps;
    
    fps << 1.0f / deltaTime;
    
    mFPSLabel.SetText( fps.str());

    if ( !mCurrentScene || mPaused)
    {
        return;
    }

    mCurrentScene->Update( deltaTime);
}

// -----------------------------------------------------------------------------

void GameController::Draw()
{
    if ( mPaused)
    {
        return;
    }

    glClear( GL_COLOR_BUFFER_BIT);
    
    glDisable( GL_DEPTH_TEST);
    
    if ( !mCurrentScene)
    {
        return;
    }
    
    mCurrentScene->Draw();
    
    mFPSLabel.Draw();
    
    glEnable( GL_DEPTH_TEST);
}




